package movee.schedule;

import movee.cluster.ClusterNodeState;
import movee.cluster.ClusterNodeStateListener;
import movee.cluster.ClusterService;
import movee.manager.core.AppDeviceDataMigration;
import movee.utils.DelayUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 定时任务
 *
 * @author movee
 */
@Service
@Slf4j
public class AppScheduledTask implements IAppScheduledTask, ClusterNodeStateListener,
        SmartInitializingSingleton, Closeable {

    private final ClusterService clusterService;
    private final AppDeviceDataMigration deviceDataMigration;


    private final AtomicBoolean enable = new AtomicBoolean(false);

    public AppScheduledTask(ClusterService clusterService,
                            AppDeviceDataMigration deviceDataMigration) {
        this.clusterService = clusterService;
        this.deviceDataMigration = deviceDataMigration;
    }

    /**
     * 放入单独的线程池中运行，且不抛出任何异常
     * 每小时执行一次
     */
    @Async("appScheduledTaskExecutor")
    @Scheduled(cron = "0 0 0/1 * * ?")
    public void scheduleGlobalTask() {
        try {

        } catch (Throwable t) {
            log.warn("BackupScheduledTask scheduleGlobalIdcTask failed. exception info: {}",
                    ExceptionUtils.getStackTrace(t));
        }
    }

    /**
     *
     * 移动记录到历史表
     */
    @Async("appScheduledTaskExecutor")
    @Scheduled(cron = "0 0 0 * * ?")
    public void migrateHistoryBackupDeviceData() {
        try {
            if (enable.get()) {
                log.info("begin migrateHistoryBackupDeviceData");
                boolean migration = true;
                while (migration) {
                    migration = deviceDataMigration.migrateHistoryBackupDeviceData();
                    DelayUtils.delayBySleep(3000L);
                }
            }

        } catch (Throwable t) {
            log.warn("BackupScheduledTask migrateHistoryBackupDeviceData failed. exception info: {}",
                    ExceptionUtils.getStackTrace(t));
        }
    }


    @Override
    public void onClusterNodeStateChange(ClusterNodeState previous, ClusterNodeState current) {

        log.info("{} onClusterNodeStateChange, previous: {}, new: {}", getName(), previous, current);
        if (current == ClusterNodeState.MASTER) {
            // 当前是master
            enable.set(true);
        } else {
            // 不是master
            enable.set(false);
        }
    }

    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }

    @Override
    public void afterSingletonsInstantiated() {
        clusterService.registerClusterNodeStateListener(this.getName(), this);
    }

    @Override
    public void close() throws IOException {
        enable.set(false);
        if (clusterService != null) {
            clusterService.removeClusterNodeStateListener(this.getName());
        }
    }
}
